package cn.tom.system.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.tom.basic.exception.BusinessException;
import cn.tom.basic.exception.StatusCode;
import cn.tom.basic.util.AjaxResult;
import cn.tom.system.jwt.JwtUtils;
import cn.tom.system.jwt.Payload;
import cn.tom.system.mapper.LogininfoMapper;
import cn.tom.system.pojo.domain.Logininfo;
import cn.tom.system.pojo.dto.LoginDto;
import cn.tom.system.service.LogininfoService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;

@Service
public class LogininfoServiceImpl implements LogininfoService {

    @Autowired
    private LogininfoMapper logininfoMapper;

    @Override
    public AjaxResult accountLogin(LoginDto loginDto) {
        //0.空值校验
        if(StrUtil.isBlank(loginDto.getUsername()) || StrUtil.isBlank(loginDto.getPassword())){
            throw new BusinessException(StatusCode.PARAM_VERIFICATION_FAILED);
        }
        //1.先根据账号去查询数据库
        QueryWrapper wrapper = new QueryWrapper<>();
        wrapper.eq("username", loginDto.getUsername());
        Logininfo logininfo = logininfoMapper.selectOne(wrapper);
        //1.1.判断为空 - 账号错误 - 抛异常
        if(logininfo == null){
            throw new BusinessException(StatusCode.ACCOUNT_ERROR);
        }
        //1.2.判断不为空 - 账号对了 - 判断密码
        //2.判断是否被禁用
        if(logininfo.getState()==0){
            throw new BusinessException(StatusCode.ACCOUNT_ERROR);
        }
        //3.判断密码
        //3.1.密码错误 - 抛异常
        String inputMd5Pwd = SecureUtil.md5(loginDto.getPassword() + logininfo.getSalt());
        if(!inputMd5Pwd.equals(logininfo.getPassword())){
            throw new BusinessException(StatusCode.ACCOUNT_ERROR);
        }
        //3.2.密码正确 - 登录成功
        Map<String, Object> map = loginSuccessJwtHandler(logininfo);
        return AjaxResult.me().setResultObj(map);
    }


    public Map<String,Object> loginSuccessJwtHandler(Logininfo logininfo){
        Map<String,Object> map = new HashMap<>(); //map给前端的，用户只有两个数据，管理员有四个数据
        Payload payload = new Payload();//用于jwt加密成token
        logininfo.setSalt(null);
        logininfo.setPassword(null);
        map.put("logininfo",logininfo);
        payload.setLogininfo(logininfo);
        //1.获取logininfo对象
        if(logininfo.getType()==0){
            //2.获取当前登录人的菜单和权限 - 细节：管理员才获取
            //你怎么知道List集合中需要什么数据？看自定义vue指令的业务和routes.js中的菜单
//            List<String> permissions = logininfoMapper.findPermissionsByLogininfoId(logininfo.getId());
//            List<Menu> menus = logininfoMapper.findMenusByLogininfoId(logininfo.getId());
//            map.put("permissions",permissions);
//            map.put("menus",menus);
//            loginData.setPermissions(permissions);
//            loginData.setMenus(menus);
            //3.将以上三个信息装到LoginData中
        }

        try {
            String jwtToken = JwtUtils.generateToken(payload);
            map.put("token",jwtToken);
        } catch (Exception e) {
            throw new BusinessException(StatusCode.LOGIN_EXCEPTION);
        }
        //5.将jwt token传到前端 -
        // 前端就可以私钥解密拿到登录信息-显示用户名，
        // 拿到当前登录人的菜单 - 做动态菜单
        // 拿到当前登录人的权限 - 做资源权限
        //但是不好意思 - 前端没有解密 - 可以将以上三个信息和token一起传递给前端
        return map;
    }

    /*@Override
    public AjaxResult wechatLogin(Map<String, String> map) {
        //一：准备三个数据
        //二：准备请求地址
        String url = WxConstants.GET_ACK_URL.replace("APPID", WxConstants.APPID)
                .replace("SECRET", WxConstants.SECRET)
                .replace("CODE", map.get("code"));
        //三：发送请求 - json字符串【后端发送请求】
        String jsonStr = HttpUtil.httpGet(url);
        //四：将json字符串转成json对象 - 获取里面的token，openid
        JSONObject jsonObject = JSONObject.parseObject(jsonStr);
        String accessToken = jsonObject.getString("access_token"); //key值从官网的返回值中copy
        String openid = jsonObject.getString("openid");
        //五：通过openid查询t_wxuser - 判断
        Wxuser wxuser = wxuserMapper.findByOpenid(openid);
        if(wxuser!=null){
            User user = userMapper.findOne(wxuser.getUserId());
            if(user != null){//绑定过了【wxuser有的，但是user_id的user对象没有了】
                Logininfo logininfo = logininfoMapper.findOne(user.getLogininfoId());
                //免密登录
                Map<String, Object> result = loginSuccessJwtHandler(logininfo);
                return AjaxResult.me().setResultObj(result);
            }
        }
        return AjaxResult.me().setSuccess(false).setResultObj("?accessToken="+accessToken+"&openid="+openid);
    }

    @Override
    public AjaxResult wechatBinder(Map<String, String> map) {
        //一：校验 - 空值
        String phone = map.get("phone");
        String verifyCode = map.get("verifyCode");
        String accessToken = map.get("accessToken");
        String openid = map.get("openid");
        if(StrUtil.isBlank(phone) || StrUtil.isBlank(verifyCode)){
            throw new BusinessException("信息不能为空");
        }
        //二：校验 - 验证码校验 - 是否过期是否正确
        Object obj = redisTemplate.opsForValue().get("binder:" + phone); //code:时间戳
        if(obj==null){
            throw new BusinessException("验证码过期");
        }
        if(!verifyCode.equals(obj.toString().split(":")[0])){
            throw new BusinessException("验证码错误");
        }
        //三：组装第三个请求地址
        String url = WxConstants.GET_USER_URL.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openid);
        //四：发送请求 - json数据 - json对象【微信用户的信息】
        String jsonStr = HttpUtil.httpGet(url);
        //五：转成Wxuser对象
        Wxuser wxuser = jsonStr2Wxuser(jsonStr);
        //六：根据phone查询User - 如果有直接绑定
        User user = userMapper.findByPhone(phone);
        if(user==null){
            //七：如果没有根据phone创建User对象【logininfo对象】 - 密码随机
            user = phone2User(phone);
            Logininfo logininfo = new Logininfo();
            BeanUtils.copyProperties(user,logininfo);
            logininfo.setType(1);//1用户
            logininfo.setDisable(true);

            logininfoMapper.add(logininfo);
            user.setLogininfoId(logininfo.getId());
            userMapper.add(user);//生成自增id
        }
        //八：将user_id设置到t_wxuser中
        wxuser.setUserId(user.getId());
        //九：将t_wxuser添加到数据库
        wxuserMapper.add(wxuser);
        Logininfo logininfo = logininfoMapper.findOne(user.getLogininfoId());
        //十：做免密登录
        Map<String, Object> result = loginSuccessJwtHandler(logininfo);
        return AjaxResult.me().setResultObj(result);
    }





    private User phone2User(String phone) {
        User user = new User();
        user.setUsername(phone);
        user.setPhone(phone);
        String salt = RandomUtil.randomString(32);
        String pwd = RandomUtil.randomString(32);
        String md5Pwd = SecureUtil.md5(pwd + salt);
        user.setSalt(salt);
        user.setPassword(md5Pwd);
        user.setState(1);
        return user;
    }

    private Wxuser jsonStr2Wxuser(String jsonStr) {
        //性别地址不能不到了
        Wxuser wxuser = new Wxuser();
        JSONObject jObj = JSONObject.parseObject(jsonStr);
        wxuser.setOpenid(jObj.getString("openid"));
        wxuser.setNickname(jObj.getString("nickname"));
        wxuser.setHeadimgurl(jObj.getString("headimgurl"));
        wxuser.setUnionid(jObj.getString("unionid"));
        return wxuser;
    }*/
}
